//////////////////////////////////////////////////////////////////////

#if !defined(AFX_SHELLPIDL_H__D704F47E_1D35_4C7C_9F90_B3071B25DCB2__INCLUDED_)
#define AFX_SHELLPIDL_H__D704F47E_1D35_4C7C_9F90_B3071B25DCB2__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#if defined USESTL
#include <vector>
#include <algorithm>
using namespace std;
typedef vector<CMenu*> vecODMenu;
#define STL_FOR_ITERATOR(t,v) for(t::iterator it=v.begin();it != v.end();it++)
#define STL_ERASE_ALL(v) v.erase(v.begin(),v.end())
#define STL_GET_CURRENT(v) *it
#define STL_ADD_ITEM(v,i) v.push_back(i);
#define STL_EMPTY(v) v.empty()
#define STL_SORT(v,f,c) TRACE0("Sorting with STL\n"); is_less_than_pidl::psf = f; sort(v.begin(),v.end(),c);
#else
#include <afxtempl.h>
typedef CArray<CMenu*,CMenu*> vecODMenu;
#define STL_FOR_ITERATOR(t,v) for (int i=0;i < v.GetSize();i++)
#define STL_ERASE_ALL(v) v.RemoveAll()
#define STL_GET_CURRENT(v) v.GetAt(i) 
#define STL_ADD_ITEM(v,i) v.Add(i);
#define STL_EMPTY(v) v.GetSize() == 0
#define STL_SORT(v,f,c) CShCMSort::is_less_than_pidl::psf = f; qsort(v.GetData(),v.GetSize(),sizeof(void*),c);
#endif

class CShCMSort
{
public:
	// sort by pidl
	class is_less_than_pidl
	{                           
	public:
		is_less_than_pidl() {}
		// STL
		bool operator()(const CShCMSort *x,const CShCMSort *y)
		{
			return ComparePidls(x,y) < 0;
		}
		int ComparePidls(const CShCMSort *x,const CShCMSort *y)
		{
			ASSERT(is_less_than_pidl::psf);
			HRESULT hr = is_less_than_pidl::psf->CompareIDs(0, x->GetPidl(), y->GetPidl());
			if (FAILED(hr))
				return 0;
			return (short)hr;
		}
		// MFC
		static int compare(const void *x, const void *y)
		{
			const CShCMSort *x1 = *(const CShCMSort**)x;
			const CShCMSort *y1 = *(const CShCMSort**)y;
			return is_less_than_pidl().ComparePidls(x1,y1);
		}
	public:
		static LPSHELLFOLDER psf;
	};

    CShCMSort(UINT nID,LPITEMIDLIST pidl,HICON hIcon,const CString &sText,DWORD dwItemData);
    CShCMSort();
    ~CShCMSort();
    CShCMSort(const CShCMSort &rOther);
    const CShCMSort &operator=(const CShCMSort &rOther);
// Properties
	void SetIndent(int nIndent);
	int GetIndent() const;
public:
    void SetImage(int nImage);
    int GetImage() const;
    void SetSelImage(int nSelImage);
    int GetSelImage() const;
    void SetOverlayImage(int nOverlayImage);
    int GetOverlayImage() const;
    void SetPidl(LPITEMIDLIST pidl);
    const LPITEMIDLIST GetPidl() const;
    void SetIcon(HICON hIcon);
    HICON GetIcon() const;
    void SetItemID(UINT nID);
    UINT GetItemID() const;
    void SetText(const CString &sText);
    const CString &GetText() const;
    void SetItemData(DWORD dwItemData);
    DWORD GetItemData() const;
private:
    // relative pidl
    LPITEMIDLIST    m_pidl;   
    int             m_nIndent;
    int             m_nImage;
    int             m_nSelImage;
    int             m_nOverlayImage;
    HICON           m_hIcon;
    UINT            m_ID;
    CString         m_sText;
    DWORD           m_dwItemData;       
};

inline void CShCMSort::SetIndent(int nIndent)
{
	m_nIndent = nIndent;
}

inline int CShCMSort::GetIndent() const
{
	return m_nIndent;
}

inline void CShCMSort::SetImage(int nImage)
{
	m_nImage = nImage;
}

inline int CShCMSort::GetImage() const
{
	return m_nImage;
}

inline void CShCMSort::SetSelImage(int nSelImage)
{
	m_nSelImage = nSelImage;
}

inline int CShCMSort::GetSelImage() const
{
	return m_nSelImage;
}

inline void CShCMSort::SetOverlayImage(int nOverlayImage)
{
	m_nOverlayImage = nOverlayImage;
}

inline int CShCMSort::GetOverlayImage() const
{
	return m_nOverlayImage;
}

inline CShCMSort::CShCMSort()   
{
    m_ID = 0;
    m_dwItemData = 0;
    m_pidl = NULL;
    m_hIcon = NULL;
	m_nIndent = 0;
	m_nImage = 0;
	m_nSelImage = 0;
	m_nOverlayImage = 0;
}

inline CShCMSort::CShCMSort(UINT nID,LPITEMIDLIST pidl,HICON hIcon,const CString &sText,DWORD dwItemData)
: 	m_ID(nID),
	m_pidl(pidl),
	m_hIcon(hIcon),
	m_sText(sText),
	m_dwItemData(dwItemData)
{
}

inline CShCMSort::~CShCMSort()
{

}


inline CShCMSort::CShCMSort(const CShCMSort &rOther)
 :  m_pidl(rOther.m_pidl),
    m_hIcon(rOther.m_hIcon),
    m_ID(rOther.m_ID),
    m_sText(rOther.m_sText),
    m_dwItemData(rOther.m_dwItemData),
	m_nIndent(rOther.m_nIndent),
	m_nImage(rOther.m_nImage),
	m_nSelImage(rOther.m_nSelImage),
	m_nOverlayImage(rOther.m_nOverlayImage)
{
}

inline const CShCMSort &CShCMSort::operator=(const CShCMSort &rOther)
{
    if (this == &rOther)
        return *this;

    m_pidl = rOther.m_pidl;
    m_hIcon = rOther.m_hIcon;
    m_ID = rOther.m_ID;
    m_sText = rOther.m_sText;
    m_dwItemData = rOther.m_dwItemData;
	m_nIndent = rOther.m_nIndent;
	m_nImage = rOther.m_nImage;
	m_nSelImage = rOther.m_nSelImage;
	m_nOverlayImage = rOther.m_nOverlayImage;

    return *this;
}

inline void CShCMSort::SetPidl(LPITEMIDLIST	pidl)
{
	m_pidl = pidl;
}

inline const LPITEMIDLIST CShCMSort::GetPidl() const
{
	return m_pidl;
}

inline void CShCMSort::SetIcon(HICON hIcon)
{
	m_hIcon = hIcon;
}

inline HICON CShCMSort::GetIcon() const
{
	return m_hIcon;
}

inline void CShCMSort::SetItemID(UINT nID)
{
	m_ID = nID;
}

inline UINT CShCMSort::GetItemID() const
{
	return m_ID;
}

inline void CShCMSort::SetText(const CString &sText)
{
	m_sText = sText;
}

inline const CString &CShCMSort::GetText() const
{
	return m_sText;
}

inline void CShCMSort::SetItemData(DWORD dwItemData)
{
	m_dwItemData = dwItemData;
}

inline DWORD CShCMSort::GetItemData() const
{
	return m_dwItemData;
}

// STL predicate helpers

#if defined USESTL
typedef vector<CShCMSort*> vecCMSort;
#define STL_SORT_FUNC is_less_than_pidl()
#else
typedef CArray<CShCMSort*,CShCMSort*> vecCMSort;
#define STL_SORT_FUNC CShCMSort::is_less_than_pidl::compare
#endif

#include <vector>

class CShellPidl  
{
public:
	CShellPidl();
	virtual ~CShellPidl();
public:
	typedef struct tagLVID
	{
		LPSHELLFOLDER lpsfParent;
		LPITEMIDLIST  lpi;
		ULONG         ulAttribs;
	} LVITEMDATA, *LPLVITEMDATA;

	typedef struct tagTVID
	{
		LPSHELLFOLDER lpsfParent;
		LPITEMIDLIST  lpi;
		LPITEMIDLIST  lpifq;
		LPARAM		 lParam;
	} TVITEMDATA, *LPTVITEMDATA;

	virtual BOOL PopupTheMenu(HWND hwnd, LPSHELLFOLDER lpsfParent, LPITEMIDLIST  *lpi, UINT cidl, LPPOINT lppt);
	virtual BOOL HandleMenuMsg(HWND hwnd, LPSHELLFOLDER lpsfParent,
								LPITEMIDLIST  lpi, UINT uMsg, WPARAM wParam, LPARAM lParam);
	STDMETHOD(StrRetToStr)(STRRET StrRet, LPTSTR* str, LPITEMIDLIST pidl);
	STDMETHOD(ResolveChannel)(IShellFolder* pFolder, LPCITEMIDLIST pidl, LPTSTR* lpszURL);
	STDMETHOD(ResolveHistoryShortcut)(LPSHELLFOLDER pFolder,LPCITEMIDLIST *ppidl,CString &sURL);
	STDMETHOD(ResolveInternetShortcut)(LPCTSTR lpszLinkFile, LPTSTR* lpszURL);
	STDMETHOD(ResolveLink)(HWND hWnd,LPCTSTR lpszLinkFile, LPTSTR* lpszPath);
	STDMETHOD(SHPathToPidlEx)(LPCTSTR szPath, LPITEMIDLIST* ppidl, LPSHELLFOLDER pFolder=NULL);
	STDMETHOD(SHPidlToPathEx)(LPCITEMIDLIST pidl, CString &sPath, LPSHELLFOLDER pFolder=NULL,DWORD dwFlags=SHGDN_FORPARSING);
	LPITEMIDLIST GetFullyQualPidl(LPSHELLFOLDER lpsf, LPITEMIDLIST lpi);
	LPITEMIDLIST CopyItemIDList(LPITEMIDLIST pidl);
	LPITEMIDLIST CopyItemID(LPITEMIDLIST pidl,int n=0);
	LPITEMIDLIST CopyLastItemID(LPITEMIDLIST pidl);
	LPITEMIDLIST CopyAbsItemID(LPITEMIDLIST pidl,int n);
	LPITEMIDLIST ConcatPidl(LPITEMIDLIST pidlDest,LPITEMIDLIST pidlSrc);
	LPITEMIDLIST Next(LPCITEMIDLIST pidl);
	LPSHELLFOLDER GetFolder(LPITEMIDLIST pidl);
	LPSHELLFOLDER GetDesktopFolder();
	LPCITEMIDLIST GetEmptyPidl();
	bool IsDesktopFolder(LPSHELLFOLDER psFolder);
	BOOL DoShellContectMenu(HWND hwnd, LPSHELLFOLDER lpsfParent, LPITEMIDLIST  lpi, LPPOINT lppt);
	void DoDefaultShellContectMenuCommand(HWND hWnd, LPSHELLFOLDER lpsfParent, LPITEMIDLIST lpi);
	void DoLastShellContectMenuCommand(HWND hWnd, LPSHELLFOLDER lpsfParent, LPITEMIDLIST lpi);
	UINT GetSize(LPCITEMIDLIST pidl);
	static CString GetFileSizeString(LPCTSTR szFilePath);
	static CString GetLastWriteTimeString(LPCTSTR szFilePath);
	static BOOL WINAPI FileExist(LPCTSTR szFileName);
	static BOOL WINAPI IsDirectory(LPCTSTR szPathName);
	static void WINAPI OpenFileWith(CString szFileName);
	UINT GetItemIdCount(LPCITEMIDLIST pidl);
	void GetTypeName(LPITEMIDLIST lpi,CString &sTypeName);
	static CString GetTypeName(LPCTSTR szFilePath, BOOL bFile = TRUE);
	void GetDisplayName(LPITEMIDLIST lpi,CString &sDisplayName);
	static int GetShellIcon(LPITEMIDLIST lpi, UINT uFlags);
	static int GetShellIcon(CString & sName, BOOL bFileExist = FALSE , BOOL bOpen = FALSE ,  BOOL bSmall = TRUE );
	void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, int &iImage, int &iSelectedImage);
	BOOL GetName (LPSHELLFOLDER lpsf, LPITEMIDLIST lpi, DWORD dwFlags, LPSTR sFriendlyName);
	bool ComparePidls(LPSHELLFOLDER pFolder,LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2);
	bool CompareMemPidls(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2);
	IMalloc *GetMalloc();
	void FreePidl(LPITEMIDLIST pidl);
	void Free(void *pv);
protected:
	STDMETHOD(GetURL)(IDataObject *pDataObj,CString &sURL);
private:
	ITEMIDLIST		m_EmptyPidl;
	LPMALLOC		m_pMalloc;
	LPSHELLFOLDER	m_psfDesktop;
};

using namespace std;
typedef vector<CShellPidl::LPTVITEMDATA> vecItemData;

#endif // !defined(AFX_SHELLPIDL_H__D704F47E_1D35_4C7C_9F90_B3071B25DCB2__INCLUDED_)
